package com.isczy.serurity.filter;

import cn.hutool.core.util.StrUtil;
import com.isczy.serurity.security.TokenManager;
import com.isczy.utils.DataResult;
import com.isczy.utils.ResponseUtil;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.util.StringUtils;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * <p>
 * 授权过滤器
 * </p>
 *
 */
public class TokenAuthenticationFilter extends BasicAuthenticationFilter {

    private TokenManager tokenManager;
    private RedisTemplate redisTemplate;

    public TokenAuthenticationFilter(AuthenticationManager authManager, TokenManager tokenManager,RedisTemplate redisTemplate) {
        super(authManager);
        this.tokenManager = tokenManager;
        this.redisTemplate = redisTemplate;
    }

    /***
     * ***************************************
     * 功能描述:拦截非放行请求：执行授权过程
     * @param req
     * @param res
     * @param chain
     * @return
     * @author create: TODO 人员:【ChangZiYang】类型:【新增方法】日期:【2021-01-27 10:02】
     * @author modify:
     */
    @Override
    protected void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain chain)
            throws IOException, ServletException {
        if(req.getRequestURI().indexOf("admin") == -1) {
            chain.doFilter(req, res);
            return;
        }
        try {
            setAuthentication(req,res);
        } catch (Exception e) {
            ResponseUtil.out(res, DataResult.builder().errorBuild());
        }
        chain.doFilter(req, res);
    }

    /***
     * ***************************************
     * 功能描述:设置权限信息，根据token信息获取用户名，再从redis中获取权限信息
     * @param request
     * @param res
     * @return
     * @author create: TODO 人员:【ChangZiYang】类型:【新增方法】日期:【2021-01-27 12:42】
     * @author modify:
     */
    private void setAuthentication(HttpServletRequest request,HttpServletResponse res) {
        UsernamePasswordAuthenticationToken authentication;
        // token置于header里
        String token = request.getHeader("token");
        if (StrUtil.isNotBlank(token)) {
            String userName = tokenManager.getUserFromToken(token);
            if (StrUtil.isNotEmpty(userName)){
                List<String> permissionValueList = (List<String>) redisTemplate.opsForValue().get(userName);
                Collection<GrantedAuthority> authorities = new ArrayList<>();
                for(String permissionValue : permissionValueList) {
                    if(StringUtils.isEmpty(permissionValue)) continue;
                    SimpleGrantedAuthority authority = new SimpleGrantedAuthority(permissionValue);
                    authorities.add(authority);
                }
                authentication = new UsernamePasswordAuthenticationToken(userName, token, authorities);
                SecurityContextHolder.getContext().setAuthentication(authentication);
            }else {
                ResponseUtil.out(res, DataResult.builder()
                        .message("token失效,请重新登录").errorBuild());
            }
        }else{
            ResponseUtil.out(res, DataResult.builder()
                    .message("非法操作,无权访问").errorBuild());
        }
    }
}
